#pragma once
#include"noncopyable.h"
#include<pthread.h>
#include<stdio.h>
#include<stdlib.h>

/*
muduo的单例模式采用模板类实现，它内部维护一个模板参数的指针，
可以生成任何一个模板参数的单例。凭借SFINAE技术muduo库可以检测模板参数如果是类的话，
并且该类注册了一个no_destroy()方法，那么muduo库不会去自动销毁它。否则muduo库会在init时，
利用pthread_once()函数为模板参数，注册一个atexit时的destroy()垃圾回收方法，实现自动垃圾回收。
智能指针也能达到类似的效果，我们平时写的单例模式在Singleton中写一个Garbage类也可以完成垃圾回收。

muduo库与我们平时使用mutex取get_instance不同，
我们平时通常在get_Instance中只产生对象，在此之前需要先手动调用init()方法。
但muduo库使用了pthread_once()函数，该函数只会执行一次，且是线程安全的函数，
所以只有在我们第一次get_instance()时，才会自动调用Init()方法。此后只会获取实例

*/
template<typename T>
class Singleton:noncopyable{
public:
    static T& instance()
    {
        pthread_once(&ponce_,&Singleton::init);
        return *value_;
    }
private:
    Singleton();
    ~Singleton();
    static pthread_once_t ponce_;//pthread_once 需要是静态的
    static T* value_;
    static void init(){
        value_=new T();
        atexit(destory);////其作用是注册某一个函数，当进程执行结束时，会自动调用注册的函数
    }
    static void destory(){
        typedef char T_must_be_complete_type[sizeof(T) == 0 ? -1 : 1];
    //定义了一个固定大小的char型数组，数组名为type_must_be_complete，数组大小是多少呢？是sizeof(T)?1:-1
        delete value_;
        //printf("destory\n");
    }
};
template<typename T>
pthread_once_t Singleton<T>::ponce_ = PTHREAD_ONCE_INIT;

template<typename T>
T* Singleton<T>::value_ = NULL;